//
//  HKEPPhonticCaculateManager.m
//  文字拼音对齐计算
//
//  Created by GZCP1897 on 2017/12/29.
//  Copyright © 2017年 GZCP1897. All rights reserved.
//

#import "HKEPPhonticCaculateManager.h"
#import "HKEPSubTextModel.h"

@interface HKEPPhonticCaculateManager()

@property (nonatomic, strong) NSString *textFontFamily;
@property (nonatomic, strong) NSString *phonticFontFamily;
@property (nonatomic, assign, readonly) CGFloat textFontSize;
@property (nonatomic, assign, readonly) CGFloat phonticFontSzie;
@end

@implementation HKEPPhonticCaculateManager

- (NSAttributedString *)caculateAttributedStringWithTextString:(NSString *)text phonticString:(NSString *)phontic widthMax:(CGFloat)widthMax{
    //1. 处理文字和拼音
    NSString *textStr = [self dealSpaceString:text];
    NSString *phonticStr = [self dealSpaceString:phontic];
    
    //2. 获取字体  规则 拼音数字上标的字号为原来字号的一半
    UIFont *textFont = [UIFont fontWithName:self.textFontFamily size:self.textFontSize];
    UIFont *phonticFont = [UIFont fontWithName:self.phonticFontFamily size:self.phonticFontSzie];
    UIColor *textColor = [UIColor colorWithRed:0 green:182./255. blue:172./255. alpha:1];
    UIColor *phonticColor = [UIColor colorWithRed:0 green:73./255. blue:134./255. alpha:1];
    
    NSDictionary<NSAttributedStringKey, id> *textAttributesDic = @{NSFontAttributeName : textFont, NSKernAttributeName : @0, NSForegroundColorAttributeName : textColor};
    NSDictionary<NSAttributedStringKey, id> *phonticAttributesDic = @{NSFontAttributeName : phonticFont, NSKernAttributeName : @0, NSForegroundColorAttributeName : phonticColor};
    
    //3. 解析 获取拼音和文字的数组
    NSArray *textArray = [self subTextArrayWithText:textStr attributes:textAttributesDic];
    NSArray *phonticArray = [self subPhonticArrayWithPhontic:phonticStr attributes:phonticAttributesDic];
    
    
    //4.根据textWidth处理换行
    NSAttributedString *result = [self dealNewLineWithTextArray:textArray phonticArray:phonticArray textWidth:widthMax];
    
    //5.赋值
    _textString = textStr;
    _phonticString = phonticStr;
    _textWidthMax = widthMax;
    _attributeString = result;
    return _attributeString;
}

/**
 处理解析到的文字和拼音数组 生成富文本
 
 @param textArray 文字数组
 @param phonticArray 拼音数组
 @param textWidth 要显示的Lable的宽度
 */
- (NSAttributedString *)dealNewLineWithTextArray:(NSArray <HKEPSubTextModel *> *)textArray phonticArray:(NSArray <HKEPSubTextModel *> *)phonticArray textWidth:(CGFloat)textWidth{
    NSUInteger count = textArray.count;
    if (count != phonticArray.count) {
        NSLog(@"拼音和文字数量不一致，请检查");
        return nil;;
    }
    
    NSMutableAttributedString *result = nil;
    
    NSMutableArray *currentTextArray = [NSMutableArray arrayWithArray:textArray];
    NSMutableArray *currentPhonticArray = [NSMutableArray arrayWithArray:phonticArray];
    
    while (currentTextArray.count) {
        //计算当前行 头部缩进
        CGFloat phonticHeadIndent = 0.0;
        NSError *error = nil;
        
        NSMutableAttributedString *currentAttributes = [self dealNewLineWithwidthMax:textWidth TextArray:currentTextArray phonticArray:currentPhonticArray phonticHeader:&phonticHeadIndent error:&error];
        if (error) {
            NSLog(@"error -- %@", error.localizedDescription);
            break;
        }
        if (result.string.length == 0) {
            //first
            result = currentAttributes;
        }else{
            //组合数据
            NSAttributedString *newLine = [[NSAttributedString alloc] initWithString:@"\n"];
            [result appendAttributedString:newLine];
            [result appendAttributedString:currentAttributes];
        }
    }
    
    return [[NSAttributedString alloc] initWithAttributedString:result];
}

/**
 对每行标取进行对照计算

 @param widthMax 显示出来的时候 每行的最大宽度
 @param textArray 解析出来的文字数组
 @param phonticArray 解析的拼音数组
 @param headerIndent 指向当前头间距的指针
 @return 计算的这一行的富文本
 */
- (NSMutableAttributedString *)dealNewLineWithwidthMax:(CGFloat)widthMax TextArray:(NSMutableArray *)textArray phonticArray:(NSMutableArray *)phonticArray  phonticHeader:(CGFloat *)headerIndent error:(NSError **)error{
    CGFloat phonticHeaderIndent = 0.0;//拼音头间距
    CGFloat textHeaderIndent = 0.0;//文字的头间距
    CGFloat currentWidth = 0.0;//文字对应之后的最大间距
    
    NSMutableAttributedString *result = [[NSMutableAttributedString alloc] init];
    NSMutableAttributedString *textAttributesTmp = [[NSMutableAttributedString alloc] init];
    
    CGFloat lastPhonticInset = 0.0;
    CGFloat lastTextInset = 0.0;
    
    NSUInteger count = textArray.count;
    for (int i = 0; i < count; i++) {
        HKEPSubTextModel *textModel = [textArray firstObject];
        HKEPSubTextModel *phonticModel = [phonticArray firstObject];
        
        CGFloat phoHeader = 0.0;
        CGFloat phoBottom = 0.0;
        CGFloat texHeader = 0.0;
        CGFloat texBottom = 0.0;
        
        //处理间距
        CGFloat caculateWidth = [self caculateWidthMaxIgnoreTopsignWithTextWidth:textModel.textWidth phonticWidth:phonticModel.phonticWidth topsignWidth:phonticModel.topSignWidth phonticHeaderIndent:&phoHeader phonticBottomIndent:&phoBottom textHeaderIndent:&texHeader textBottomIndent:&texBottom];
        
        CGFloat attempt = currentWidth + caculateWidth;
        if (attempt > widthMax) {
            if (i == 0) {
                *error = [[NSError alloc] initWithDomain:@"widthMax" code:-1 userInfo:@{NSLocalizedDescriptionKey : @"特么的最大宽度太小了"}];
                return nil;
            }
            //跳出循环
            break;
        }
        currentWidth = attempt;
    
        //宽度处理
        if (result.string.length == 0) {
            phonticHeaderIndent += phoHeader;
            textHeaderIndent += texHeader;
        }else{
            //把上次遗留的间距添加上
            [result addAttributes:@{NSKernAttributeName : [[NSNumber alloc] initWithFloat:phoHeader + lastPhonticInset]} range:NSMakeRange(result.string.length-1, 1)];
            [textAttributesTmp addAttributes:@{NSKernAttributeName : [[NSNumber alloc] initWithFloat:lastTextInset + texHeader]} range:NSMakeRange(textAttributesTmp.string.length-1, 1)];
        }
        lastPhonticInset = phoBottom;
        lastTextInset = texBottom;
        
        //拼接富文本
        [result appendAttributedString:phonticModel.textAttribute];
        [textAttributesTmp appendAttributedString:textModel.textAttribute];
        
        //移除首个
        [textArray removeObjectAtIndex:0];
        [phonticArray removeObjectAtIndex:0];
    }
    
    //计算间距并拼接文字富文本
    CGFloat widthResidue = (widthMax - currentWidth)*0.5;
    
    NSMutableParagraphStyle *phonticStyle = [[NSMutableParagraphStyle alloc] init];
    phonticStyle.firstLineHeadIndent = widthResidue + phonticHeaderIndent;
    [result addAttributes:@{NSParagraphStyleAttributeName : phonticStyle} range:NSMakeRange(0, result.string.length)];
    
    NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle alloc] init];
    textStyle.firstLineHeadIndent = widthResidue + textHeaderIndent;
    [textAttributesTmp addAttributes:@{NSParagraphStyleAttributeName : textStyle} range:NSMakeRange(0, textAttributesTmp.string.length)];
    
    NSAttributedString *newLine = [[NSAttributedString alloc] initWithString:@"\n"];
    [result appendAttributedString:newLine];
    [result appendAttributedString:textAttributesTmp];
    
    return result;
}

#pragma mark - 解析
- (NSArray <HKEPSubTextModel *> *)subTextArrayWithText:(NSString *)text attributes:(NSDictionary<NSAttributedStringKey, id> *)attributes{
    
    NSMutableArray *subTextArray = [NSMutableArray array];
    
    //截取文字 忽略空格 反斜杠注意标出
    for (int i = 0; i < text.length; i++) {
        NSString *subStr = [text substringWithRange:NSMakeRange(i, 1)];
        
        if ([subStr isEqualToString:@" "]) {
            break;
        }
        CGFloat subStrWidth = [self caculateTextWidthText:subStr attributes:attributes];
        
        HKEPSubTextModel *model = [[HKEPSubTextModel alloc] init];
        model.text = subStr;
        model.textAttribute = [[NSAttributedString alloc] initWithString:subStr attributes:attributes];
        model.textWidth = subStrWidth;
        if ([subStr isEqualToString:@"/"]) {
            model.isBackslash = YES;
        }else{
            model.isBackslash = NO;
        }
        [subTextArray addObject:model];
    }
    return [[NSArray alloc] initWithArray:subTextArray];
}
//上标为当前拼音字号的一半大小
- (NSArray <HKEPSubTextModel *> *)subPhonticArrayWithPhontic:(NSString *)phontic attributes:(NSDictionary<NSAttributedStringKey, id> *)attributes{
    NSMutableArray *subPhonticArray = [NSMutableArray array];
    NSArray *array = [phontic componentsSeparatedByString:@" "];//按照空格分割
    
    for (NSString *subStr in array) {
        
        if ([subStr containsString:@"/"])
        {//判断有斜杠
            
            NSArray *subBackslashArray = [subStr componentsSeparatedByString:@"/"];
            
            for (int i = 0; i < subBackslashArray.count; i++) {
                NSString *subBackslashStr = subBackslashArray[i];
                //对拼音进行处理
                if (subBackslashStr && (![subBackslashStr isEqualToString:@""])) {
                    HKEPSubTextModel *model = [self dealSubPhonticWithString:subBackslashStr attributes:attributes];
                    [subPhonticArray addObject:model];
                }
                if (i < subBackslashArray.count -1) {
                    //不是最后一个 添加一个/的model
                    HKEPSubTextModel *backslashModel = [[HKEPSubTextModel alloc] init];
                    backslashModel.text = @"/";
                    backslashModel.textAttribute = [[NSAttributedString alloc] initWithString:@"/" attributes:attributes];
                    backslashModel.phonticWidth = backslashModel.textWidth = [self caculateTextWidthText:@"/" attributes:attributes];
                    backslashModel.topSignWidth = 0.;
                    backslashModel.isBackslash = YES;
                    [subPhonticArray addObject:backslashModel];
                }
            }
        }else
        {//没包含反斜杠
            HKEPSubTextModel *model = [self dealSubPhonticWithString:subStr attributes:attributes];
            [subPhonticArray addObject:model];
        }
    }
    
    return subPhonticArray;
}
- (HKEPSubTextModel *)dealSubPhonticWithString:(NSString *)subPhontic attributes:(NSDictionary<NSAttributedStringKey, id> *)attributes{
    
    HKEPSubTextModel *model = [[HKEPSubTextModel alloc] init];
    model.text = subPhontic;
    model.isBackslash = NO;
    
    //先计算没有上标的情况下的宽度 再查找之后再进行处理
    NSMutableAttributedString *attributedStringM = [[NSMutableAttributedString alloc] initWithString:subPhontic attributes:attributes];
    CGFloat textWidth = [self caculateTextWidthText:subPhontic attributes:attributes];
    __block CGFloat topSignWidth = 0.0;
    __block CGFloat phonticWidth = textWidth;
    
    NSString *regularPattern = @"[0-9]{1,}";
    NSError *error = nil;
    NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regularPattern options:NSRegularExpressionCaseInsensitive error:&error];
    if (error) {
        NSLog(@"error %@", error);
    }
    
    //获取上标的富文本
    NSDictionary *topsignAttributes = [self getTopSignAttributesWithCurrentAttributes:attributes];
    
    [regular enumerateMatchesInString:subPhontic options:NSMatchingReportCompletion range:NSMakeRange(0, subPhontic.length) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
        NSRange matchRange = result.range;
        NSString *matchStr = [subPhontic substringWithRange:matchRange];
        if (matchStr && (![matchStr isEqualToString:@""])) {
            [attributedStringM addAttributes:topsignAttributes range:matchRange];
            //计算在正常和上标情况下matchStr的宽度
            
            CGFloat matchNormalW = [self caculateTextWidthText:matchStr attributes:attributes];
            CGFloat matchTopsignW = [self caculateTextWidthText:matchStr attributes:topsignAttributes];
            topSignWidth += matchTopsignW;
            phonticWidth -= matchNormalW;
        }
    }];
    
    model.topSignWidth = topSignWidth;
    model.phonticWidth = phonticWidth;
    model.textWidth = topSignWidth + phonticWidth;
    model.textAttribute = [[NSAttributedString alloc] initWithAttributedString:attributedStringM];
    return model;
}

#pragma mark - 处理 计算
/**
 在忽略上边的情况下 计算对照之后的最大宽度

 @param TextWidth 汉字的宽度
 @param phonticWidth 不含上标的拼音的宽度
 @param topsignWidth 上标的宽度
 @return 适配的最大宽度
 */
- (CGFloat)caculateWidthMaxIgnoreTopsignWithTextWidth:(CGFloat)TextWidth phonticWidth:(CGFloat)phonticWidth topsignWidth:(CGFloat)topsignWidth phonticHeaderIndent:(CGFloat *)phonticHeaderIndent phonticBottomIndent:(CGFloat *)phonticBottomIndent textHeaderIndent:(CGFloat *)textHeaderIndent textBottomIndent:(CGFloat *)textBottomIndent{
    
    CGFloat maxW = 0.0;
    CGFloat phoHeader = 0.0;
    CGFloat phoBottom = 0.0;
    CGFloat textHeader = 0.0;
    CGFloat textBottom = 0.0;
    
    CGFloat inset = ABS(TextWidth - phonticWidth)*0.5;
    if (TextWidth >= phonticWidth) {
        if (inset >= topsignWidth)
        {
            phoBottom = inset - topsignWidth;
        }else
        {
            textBottom = topsignWidth - inset;
        }
        phoHeader = inset;
        maxW = TextWidth + textBottom;
    }else{
        maxW = phonticWidth + topsignWidth;
        textHeader = inset;
        textBottom = inset + topsignWidth;
    }
    
    *phonticHeaderIndent = phoHeader;
    *phonticBottomIndent = phoBottom;
    *textHeaderIndent = textHeader;
    *textBottomIndent = textBottom;
    return maxW;
}
/**
 处理重复的空格 并去除首尾空格
 
 @param string 需要处理的字符串
 @return 处理后的字符串
 */
- (NSString *)dealSpaceString:(NSString *)string{
    //1. 空格去重
    NSString *result = string.copy;
    for (int i = 0; i < INT_MAX; i++) {
        if ([result containsString:@"  "]) {
            result = [result stringByReplacingOccurrencesOfString:@"  " withString:@" "];
        }else{
            break;
        }
    }
    //2.去掉前后的空格
    if ([result hasPrefix:@" "] || [result hasSuffix:@" "]) {
        result = [result stringByTrimmingCharactersInSet:[NSCharacterSet  whitespaceAndNewlineCharacterSet]];
    }
    return result;
}
/**
 计算相同字号的文字宽度
 
 @param text 文字
 @param attributes 文字的富文本
 @return 文字的宽度
 */
- (CGFloat)caculateTextWidthText:(NSString *)text attributes:(NSDictionary<NSAttributedStringKey, id> *)attributes{
    CGRect bounds = [text boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
    return bounds.size.width;
}

#pragma mark - 字体相关
//字体变为原来字号一半
- (NSDictionary<NSAttributedStringKey, id> *)getTopSignAttributesWithCurrentAttributes:(NSDictionary<NSAttributedStringKey, id> *)current{
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:current];
    UIFont *font = [dic objectForKey:NSFontAttributeName];
    UIFont *topSignFont = [UIFont fontWithName:font.familyName size:font.pointSize *0.5];
    [dic setObject:topSignFont forKey:NSFontAttributeName];
    
    //    [dic setObject:[NSNumber numberWithFloat:fabs(font.xHeight - topSignFont.xHeight)] forKey:NSBaselineOffsetAttributeName];
    [dic setObject:[NSNumber numberWithFloat:fabs(font.lineHeight - topSignFont.lineHeight)] forKey:NSBaselineOffsetAttributeName];
    
    //    [dic setObject:[UIColor greenColor] forKey:NSForegroundColorAttributeName];
    return [NSDictionary dictionaryWithDictionary:dic];
}
//文字字体大小 42.0
- (CGFloat)textFontSize{
    return 42.0;
}
//拼音字体大小 20.0
- (CGFloat)phonticFontSzie{
    return 20.0;
}
- (NSString *)textFontFamily{
    return @".SFUIDisplay-Semibold";
}
- (NSString *)phonticFontFamily{
    return @"Times New Roman";
}
@end
